#include "VideoDecode.h"
#include "mediaPriv.h"
#include "Util/logc.h"


namespace Media{

std::mutex 	VideoDecode::sm_cntMutex;
int  VideoDecode::sm_decodeCnt = 0;

std::map<int, VideoDecode *> VideoDecode::sm_decoderMap;
std::recursive_mutex 		 VideoDecode::sm_mapMutex;

int VideoDecode::getVideoDecChannel(void)
{
    std::lock_guard<std::mutex> guard(sm_cntMutex);

    return sm_decodeCnt++;   
}


VideoDecode *VideoDecode::instance(int channel)
{
    if(channel > VDEC_MAX_CHN_NUM - 1)
    {
        errorf("channel is over VDEC_MAX_CHN_NUM \n");
        return NULL;
    }
    
    std::lock_guard<std::recursive_mutex> guard(sm_mapMutex);
    
	if(sm_decoderMap.find(channel) == sm_decoderMap.end())
	{
		sm_decoderMap[channel] = new VideoDecode(channel);
	}

	return sm_decoderMap[channel];
}


VideoDecode::VideoDecode(int channel) 
: m_channel(channel)
, m_started(false)
{
	if(!createDecoder())
	{
		errorf("VideoDecode create error! channel %d", m_channel);
		return ;
	}
	tracef("createDecoder %d success\n", channel);
	
	if(!decodeInit())
	{
		errorf("Init failed");
	}
}

bool VideoDecode::createDecoder()
{
    int status;
    VideoDecDesc decDesc;

    decDesc.card = 0;
    decDesc.channel = m_channel;
    status = createVideoDecoder(&decDesc, &m_videoDecoder);
    if (status)
    {
        return false;
    }

    return true;
}

bool VideoDecode::decodeInit()
{
    VideoDecFormat decFormat;
    memset(&decFormat, 0, sizeof(VideoDecFormat));
    decFormat.type = videoEncH264;
    
    if(!setFormat(&decFormat))
    {
    	return false;
    }
    return true;
}

bool VideoDecode::getFormat(VideoDecFormat *format)
{
	if(!format)
	{
	    errorf("format is NULL \n");
		return false;
	}	
	memcpy(format, &m_format, sizeof(VideoDecFormat));
	return true;
}

bool VideoDecode::setFormat(VideoDecFormat *format)
{
    if(!format || !m_videoDecoder)
	{
	    errorf("format or m_videoDecoder is NULL \n");
		return false;
	}
		
    return (m_videoDecoder->setFormat(m_videoDecoder, format) >= 0);
}

bool VideoDecode::start()
{
    if(!m_videoDecoder)
	{
	    errorf("m_videoDecoder is NULL \n");
		return false;
	}
    if(!m_started)
    {
        int ret = m_videoDecoder->start(m_videoDecoder);
    	if(ret)
    	{
    		return false;
    	}
    	m_started = true;
    }
	return true;
}

bool VideoDecode::stop()
{
    if(!m_videoDecoder)
	{
	    errorf("m_videoDecoder is NULL \n");
		return false;
	}
	if(m_started)
    {
        int ret = m_videoDecoder->stop(m_videoDecoder);
    	if(ret)
    	{
    		return false;
    	}
    	m_started = false;
    }
	return true;
}

bool VideoDecode::putPacket(VideoDecPacket *packet)
{
    if(!packet || !m_videoDecoder)
	{
	    errorf("packet or m_videoDecoderis NULL \n");
		return false;
	}
		
    return (m_videoDecoder->putPacket(m_videoDecoder,packet) >= 0);
}

bool VideoDecode::setStreamDisplayChn(int channel)
{
    /*if(!m_videoDecoder)
	{
	    errorf("m_videoDecoder is NULL \n");
		return false;
	}
	
    return (m_videoDecoder->setStreamDisplayChn(m_videoDecoder,channel) >= 0);*/

    return true;
}


}

